package com.ksyun.campus.metaserver.zk;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ksyun.campus.metaserver.config.MinfsProperties;
import com.ksyun.campus.metaserver.domain.DataServerInfo;
import com.ksyun.campus.metaserver.domain.MetaServerInfo;
import com.ksyun.campus.metaserver.services.LeaderElectionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.CuratorCache;
import org.apache.curator.framework.recipes.cache.CuratorCacheListener;

import org.apache.zookeeper.CreateMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;

/**
 * ZooKeeper service for service discovery and leader election
 */
@Slf4j
@Service
@DependsOn("leaderElectionService")
public class ZooKeeperService {
    
    @Autowired
    private MinfsProperties properties;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Autowired
    private CuratorFramework curator;
    
    @Autowired(required = false)
    private LeaderElectionService leaderElectionService;
    // private LeaderLatch leaderLatch; // REMOVED - using LeaderElectionService instead
    private CuratorCache metaInstancesCache;
    private CuratorCache dataServerCache;
    
    // private volatile boolean isLeader = false; // REMOVED - using LeaderElectionService instead
    // private final List<Consumer<Boolean>> leadershipListeners = new CopyOnWriteArrayList<>(); // REMOVED
    private final List<Consumer<List<DataServerInfo>>> dataServerListeners = new CopyOnWriteArrayList<>();
    
    // ZK paths
    private String rootPath;
    private String metaInstancesPath;
    private String leaderPath;
    private String dataServerPath;
    
    @PostConstruct
    public void start() throws Exception {
        try {
            log.info("Starting ZooKeeper service");
            
            // Validate dependencies
            if (properties == null) {
                throw new IllegalStateException("MinfsProperties not injected");
            }
            if (curator == null) {
                throw new IllegalStateException("CuratorFramework not injected");
            }
            
            // Initialize paths
            rootPath = properties.getZookeeper().getRootPath();
            metaInstancesPath = rootPath + "/meta/instances";
            leaderPath = rootPath + "/meta/leader";
            dataServerPath = rootPath + "/dataservers"; // 修复路径匹配问题
            
            log.info("Using injected CuratorFramework connected to ZooKeeper at {}", 
                    properties.getZookeeper().getConnectionString());
            
            // Create base paths
            createBasePaths();
            
            // Clean up invalid data before starting
            cleanupInvalidData();
            
            // Note: Instance registration is now handled by LeaderElectionService
            // registerMetaInstance(); // DISABLED - handled by LeaderElectionService
            
            // Note: Leader election is now handled by LeaderElectionService
            // startLeaderElection(); // DISABLED - using LeaderElectionService instead
            
            // Start watching data servers
            startDataServerWatcher();
            
            log.info("ZooKeeper service started successfully");
            
        } catch (Exception e) {
            log.error("Failed to start ZooKeeper service", e);
            throw e;
        }
    }
    
    @PreDestroy
    public void stop() throws Exception {
        log.info("Stopping ZooKeeper service");
        
        if (dataServerCache != null) {
            dataServerCache.close();
        }
        
        if (metaInstancesCache != null) {
            metaInstancesCache.close();
        }
        
        // leaderLatch cleanup removed - handled by LeaderElectionService
        
        if (curator != null) {
            curator.close();
        }
        
        log.info("ZooKeeper service stopped");
    }
    
    private void createBasePaths() throws Exception {
        String[] paths = {rootPath, metaInstancesPath, leaderPath, dataServerPath};
        
        for (String path : paths) {
            if (curator.checkExists().forPath(path) == null) {
                curator.create()
                        .creatingParentsIfNeeded()
                        .forPath(path);
                log.debug("Created ZK path: {}", path);
            }
        }
    }
    
    /**
     * 清理无效的DataServer数据
     */
    private void cleanupInvalidData() {
        try {
            if (curator.checkExists().forPath(dataServerPath) != null) {
                List<String> children = curator.getChildren().forPath(dataServerPath);
                
                for (String child : children) {
                    // 跳过heartbeat目录
                    if ("heartbeat".equals(child)) {
                        log.debug("Skipping heartbeat directory during cleanup");
                        continue;
                    }
                    
                    String childPath = dataServerPath + "/" + child;
                    try {
                        byte[] data = curator.getData().forPath(childPath);
                        if (data != null) {
                            String dataStr = new String(data, StandardCharsets.UTF_8);
                            
                            // 跳过空数据
                            if (dataStr.trim().isEmpty()) {
                                log.debug("Skipping empty data for child: {}", child);
                                continue;
                            }
                            
                            // 尝试解析为JSON
                            try {
                                objectMapper.readValue(dataStr, DataServerInfo.class);
                                log.debug("Valid DataServer data found: {}", child);
                            } catch (Exception e) {
                                log.warn("Invalid DataServer data found, removing: {} (data: {})", child, dataStr);
                                curator.delete().forPath(childPath);
                            }
                        }
                    } catch (Exception e) {
                        log.error("Error processing child {}: {}", child, e.getMessage());
                    }
                }
            }
        } catch (Exception e) {
            log.error("Error during data cleanup", e);
        }
    }
    
    private void registerMetaInstance() throws Exception {
        String instanceId = properties.getCluster().getInstanceId();
        String host = InetAddress.getLocalHost().getHostAddress();
        
        // Use a consistent way to get port - check system property first, then environment
        int port = 8300; // default
        String portStr = System.getProperty("server.port");
        if (portStr == null) {
            portStr = System.getenv("SERVER_PORT");
        }
        if (portStr != null) {
            try {
                port = Integer.parseInt(portStr);
            } catch (NumberFormatException e) {
                log.warn("Invalid port value: {}, using default: {}", portStr, port);
            }
        }
        
        MetaServerInfo instanceInfo = MetaServerInfo.builder()
                .instanceId(instanceId)
                .host(host)
                .port(port)
                .isLeader(false)
                .startTime(System.currentTimeMillis())
                .build();
        
        String instancePath = metaInstancesPath + "/" + instanceId;
        String instanceData = objectMapper.writeValueAsString(instanceInfo);
        
        // Check if path already exists and delete it first (avoid conflicts with LeaderElectionService)
        if (curator.checkExists().forPath(instancePath) != null) {
            log.info("Instance path already exists, removing: {}", instancePath);
            curator.delete().forPath(instancePath);
        }
        
        curator.create()
                .withMode(CreateMode.EPHEMERAL)
                .forPath(instancePath, instanceData.getBytes(StandardCharsets.UTF_8));
        
        log.info("Registered meta instance: {} at {} (port: {})", instanceId, instancePath, port);
    }
    
    // REMOVED: startLeaderElection() - now handled by LeaderElectionService
    
    private void startDataServerWatcher() throws Exception {
        dataServerCache = CuratorCache.build(curator, dataServerPath);
        
        CuratorCacheListener listener = CuratorCacheListener.builder()
                .forCreates(node -> {
                    log.debug("DataServer added: {}", node.getPath());
                    notifyDataServerListeners(getCurrentDataServers());
                })
                .forChanges((oldNode, node) -> {
                    log.debug("DataServer updated: {}", node.getPath());
                    notifyDataServerListeners(getCurrentDataServers());
                })
                .forDeletes(node -> {
                    log.debug("DataServer removed: {}", node.getPath());
                    notifyDataServerListeners(getCurrentDataServers());
                })
                .build();
        
        dataServerCache.listenable().addListener(listener);
        dataServerCache.start();
        log.info("Started DataServer watcher");
    }
    
    public boolean isLeader() {
        // Delegate to LeaderElectionService
        if (leaderElectionService != null) {
            return leaderElectionService.isLeader();
        }
        return false;
    }
    
    public String getLeaderId() throws Exception {
        // Note: This method is deprecated. Use LeaderElectionService.getCurrentLeader() instead
        return null;
    }
    
    public MetaServerInfo getLeaderInfo() throws Exception {
        String leaderId = getLeaderId();
        if (leaderId == null) {
            return null;
        }
        
        String leaderInstancePath = metaInstancesPath + "/" + leaderId;
        if (curator.checkExists().forPath(leaderInstancePath) != null) {
            byte[] data = curator.getData().forPath(leaderInstancePath);
            return objectMapper.readValue(new String(data, StandardCharsets.UTF_8), MetaServerInfo.class);
        }
        
        return null;
    }
    
    public List<DataServerInfo> getCurrentDataServers() {
        List<DataServerInfo> dataServers = new ArrayList<>();
        
        try {
            if (dataServerCache != null) {
                dataServerCache.stream().forEach(childData -> {
                    try {
                        if (childData.getData() != null) {
                            String path = childData.getPath();
                            
                            // 跳过heartbeat目录和其子节点
                            if (path.contains("/heartbeat")) {
                                log.debug("Skipping heartbeat node: {}", path);
                                return;
                            }
                            
                            String data = new String(childData.getData(), StandardCharsets.UTF_8);
                            
                            // 跳过空数据
                            if (data.trim().isEmpty()) {
                                log.debug("Skipping empty data node: {}", path);
                                return;
                            }
                            
                            // Try to parse as JSON first
                            try {
                                DataServerInfo dsInfo = objectMapper.readValue(data, DataServerInfo.class);
                                dataServers.add(dsInfo);
                                log.debug("Successfully parsed DataServer: {} from path: {}", dsInfo.getDsId(), path);
                            } catch (Exception jsonException) {
                                // If JSON parsing fails, try to handle legacy format
                                log.warn("Failed to parse DataServer info as JSON: {}. Data: {}", jsonException.getMessage(), data);
                                
                                // 尝试解析旧格式数据（纯IP地址）
                                log.debug("Attempting to parse legacy DataServer format from path: {}", path);
                                DataServerInfo legacyDsInfo = parseLegacyDataServerInfo(data, path);
                                if (legacyDsInfo != null) {
                                    dataServers.add(legacyDsInfo);
                                    log.info("Successfully parsed legacy DataServer format: {} from data: {}", 
                                            legacyDsInfo.getDsId(), data);
                                } else {
                                    log.error("Cannot parse DataServer data in any format. Path: {}, Data: {}", 
                                            path, data);
                                    // 记录详细的数据格式信息用于诊断
                                    log.error("Data length: {}, First 50 chars: {}", 
                                            data.length(), 
                                            data.length() > 50 ? data.substring(0, 50) + "..." : data);
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.error("Error processing DataServer info from path: {}", childData.getPath(), e);
                    }
                });
            }
        } catch (Exception e) {
            log.error("Error getting current data servers", e);
        }
        
        return dataServers;
    }
    
    public void addLeadershipListener(Consumer<Boolean> listener) {
        // DEPRECATED: Use LeaderElectionService.addLeadershipListener() instead
        log.warn("addLeadershipListener() is deprecated. Use LeaderElectionService.addLeadershipListener() instead");
    }
    
    public void addDataServerListener(Consumer<List<DataServerInfo>> listener) {
        dataServerListeners.add(listener);
    }
    
    // REMOVED: notifyLeadershipListeners() - leadership is now handled by LeaderElectionService
    
    private void notifyDataServerListeners(List<DataServerInfo> dataServers) {
        for (Consumer<List<DataServerInfo>> listener : dataServerListeners) {
            try {
                listener.accept(dataServers);
            } catch (Exception e) {
                log.error("Error notifying data server listener", e);
            }
        }
    }
    
    public void updateDataServerInfo(DataServerInfo dsInfo) throws Exception {
        String dsPath = dataServerPath + "/" + dsInfo.getDsId();
        String data = objectMapper.writeValueAsString(dsInfo);
        
        if (curator.checkExists().forPath(dsPath) != null) {
            curator.setData().forPath(dsPath, data.getBytes(StandardCharsets.UTF_8));
        } else {
            curator.create()
                    .withMode(CreateMode.EPHEMERAL)
                    .forPath(dsPath, data.getBytes(StandardCharsets.UTF_8));
        }
    }
    
    /**
     * 解析旧格式的DataServer信息（纯IP地址字符串）
     * 
     * @param data ZooKeeper中存储的数据
     * @param path ZooKeeper节点路径，用于提取dsId
     * @return 解析后的DataServerInfo，如果解析失败返回null
     */
    private DataServerInfo parseLegacyDataServerInfo(String data, String path) {
        try {
            String trimmedData = data.trim();
            
            // 跳过心跳数据（包含timestamp、status=alive等字段）
            if (trimmedData.contains("\"status\":\"alive\"") || 
                trimmedData.contains("\"timestamp\"") ||
                trimmedData.contains("heartbeat")) {
                log.debug("Skipping heartbeat data: {}", trimmedData);
                return null;
            }
            
            // 尝试解析JSON格式但状态值不匹配的数据
            if (trimmedData.startsWith("{") && trimmedData.contains("\"status\"")) {
                try {
                    // 先尝试修复状态值
                    String fixedData = trimmedData.replace("\"status\":\"alive\"", "\"status\":\"ACTIVE\"");
                    DataServerInfo dsInfo = objectMapper.readValue(fixedData, DataServerInfo.class);
                    log.info("Successfully parsed DataServer with fixed status: {}", dsInfo.getDsId());
                    return dsInfo;
                } catch (Exception e) {
                    log.debug("Failed to parse as fixed JSON: {}", e.getMessage());
                }
            }
            
            // 验证是否是有效的IP地址格式
            if (isValidIpAddress(trimmedData)) {
                // 从路径中提取dsId，路径格式通常是 /minfs/ds/instances/dsId
                String dsId = extractDsIdFromPath(path);
                if (dsId == null) {
                    dsId = "ds_" + trimmedData.replace(".", "_"); // 备用dsId生成方式
                }
                
                // 创建默认的DataServerInfo对象  
                // 根据dsId推断端口
                int inferredPort = getPortFromDsId(dsId);
                return DataServerInfo.builder()
                        .dsId(dsId)
                        .host(trimmedData)
                        .port(inferredPort) // 根据dsId推断端口
                        .capacityBytes(1024L * 1024L * 1024L) // 默认1GB容量
                        .usedBytes(0L) // 默认使用量为0
                        .lastSeen(LocalDateTime.now())
                        .lastHeartbeat(LocalDateTime.now())
                        .status(DataServerInfo.DataServerStatus.ACTIVE)
                        .labels(new HashMap<>())
                        .build();
            }
            
            // 尝试解析 "host:port" 格式
            if (trimmedData.contains(":") && !trimmedData.contains("{")) {
                String[] parts = trimmedData.split(":");
                if (parts.length == 2) {
                    String host = parts[0];
                    try {
                        int port = Integer.parseInt(parts[1]);
                        
                        if (isValidIpAddress(host)) {
                            String dsId = extractDsIdFromPath(path);
                            if (dsId == null) {
                                dsId = "ds_" + host.replace(".", "_") + "_" + port;
                            }
                            
                            return DataServerInfo.builder()
                                    .dsId(dsId)
                                    .host(host)
                                    .port(port)
                                    .capacityBytes(1024L * 1024L * 1024L) // 默认1GB容量
                                    .usedBytes(0L)
                                    .lastSeen(LocalDateTime.now())
                                    .lastHeartbeat(LocalDateTime.now())
                                    .status(DataServerInfo.DataServerStatus.ACTIVE)
                                    .labels(new HashMap<>())
                                    .build();
                        }
                    } catch (NumberFormatException e) {
                        log.debug("Invalid port number in: {}", trimmedData);
                    }
                }
            }
            
        } catch (Exception e) {
            log.error("Error parsing legacy DataServer info: {}", data, e);
        }
        
        return null;
    }
    
    /**
     * 根据DataServer ID推断端口号
     */
    private int getPortFromDsId(String dsId) {
        try {
            // 从dsId中提取索引，如 data-server-1 -> 1
            String indexStr = dsId.replaceAll("data-server-", "");
            int index = Integer.parseInt(indexStr);
            
            // 端口映射：9001, 9002, 9003, 9004
            switch (index) {
                case 1: return 9001;
                case 2: return 9002; 
                case 3: return 9003;
                case 4: return 9004;
                default: return 9001 + (index - 1); // 对于其他索引的通用规则
            }
        } catch (Exception e) {
            log.warn("Could not parse port from dsId: {}, using default: 9001", dsId);
            return 9001; // 默认端口改为9001
        }
    }
    
    /**
     * 验证是否是有效的IP地址
     */
    private boolean isValidIpAddress(String ip) {
        if (ip == null || ip.trim().isEmpty()) {
            return false;
        }
        
        String[] parts = ip.trim().split("\\.");
        if (parts.length != 4) {
            return false;
        }
        
        try {
            for (String part : parts) {
                int num = Integer.parseInt(part);
                if (num < 0 || num > 255) {
                    return false;
                }
            }
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }
    
    /**
     * 从ZooKeeper路径中提取dsId
     */
    private String extractDsIdFromPath(String path) {
        if (path == null) {
            return null;
        }
        
        // 路径格式通常是 /minfs/dataservers/dsId
        String[] parts = path.split("/");
        if (parts.length > 0) {
            String dsId = parts[parts.length - 1]; // 返回最后一部分作为dsId
            log.debug("Extracted dsId '{}' from path '{}'", dsId, path);
            return dsId;
        }
        
        return null;
    }
    
    /**
     * 清理所有DataServer注册数据
     * 提供给管理接口使用
     */
    public Map<String, Object> cleanupAllDataServerRegistrations() {
        Map<String, Object> result = new HashMap<>();
        int removedCount = 0;
        
        try {
            log.info("Starting cleanup of all DataServer registration data");
            
            String dataServerPath = rootPath + "/dataservers";
            
            // 获取所有子节点
            if (curator.checkExists().forPath(dataServerPath) != null) {
                List<String> children = curator.getChildren().forPath(dataServerPath);
                
                for (String child : children) {
                    // 跳过heartbeat目录
                    if ("heartbeat".equals(child)) {
                        continue;
                    }
                    
                    String childPath = dataServerPath + "/" + child;
                    try {
                        byte[] data = curator.getData().forPath(childPath);
                        if (data != null) {
                            String dataStr = new String(data, StandardCharsets.UTF_8);
                            log.info("Removing DataServer node: {} with data: {}", child, dataStr);
                            
                            curator.delete().forPath(childPath);
                            removedCount++;
                        }
                    } catch (Exception e) {
                        log.error("Error removing DataServer node {}: {}", child, e.getMessage());
                    }
                }
            }
            
            // 清理heartbeat目录中的数据
            String heartbeatPath = dataServerPath + "/heartbeat";
            if (curator.checkExists().forPath(heartbeatPath) != null) {
                List<String> heartbeatChildren = curator.getChildren().forPath(heartbeatPath);
                for (String child : heartbeatChildren) {
                    String childPath = heartbeatPath + "/" + child;
                    try {
                        curator.delete().forPath(childPath);
                        log.info("Removed heartbeat node: {}", child);
                    } catch (Exception e) {
                        log.error("Error removing heartbeat node {}: {}", child, e.getMessage());
                    }
                }
            }
            
            result.put("success", true);
            result.put("removedCount", removedCount);
            result.put("message", "Successfully cleaned up all DataServer registration data");
            
            log.info("Cleanup completed, removed {} DataServer nodes", removedCount);
            
        } catch (Exception e) {
            log.error("Error during DataServer cleanup", e);
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 获取ZooKeeper中的原始DataServer数据
     */
    public Map<String, Object> getRawDataServerData() {
        Map<String, Object> result = new HashMap<>();
        Map<String, String> rawData = new HashMap<>();
        
        try {
            String dataServerPath = rootPath + "/dataservers";
            
            if (curator.checkExists().forPath(dataServerPath) != null) {
                List<String> children = curator.getChildren().forPath(dataServerPath);
                
                for (String child : children) {
                    if ("heartbeat".equals(child)) {
                        continue;
                    }
                    
                    String childPath = dataServerPath + "/" + child;
                    try {
                        byte[] data = curator.getData().forPath(childPath);
                        if (data != null) {
                            String dataStr = new String(data, StandardCharsets.UTF_8);
                            rawData.put(child, dataStr);
                        }
                    } catch (Exception e) {
                        rawData.put(child, "Error reading data: " + e.getMessage());
                    }
                }
            }
            
            result.put("success", true);
            result.put("rawData", rawData);
            result.put("totalNodes", rawData.size());
            
        } catch (Exception e) {
            log.error("Error getting raw DataServer data", e);
            result.put("success", false);
            result.put("error", e.getMessage());
        }
        
        return result;
    }
}
